class Maybe { // 容器类型 父类
  static just(a) {
    return new Just(a);
  }

  static nothing() {
    return new Nothing();
  }

  static fromNullLable(a) {
    return a !== null && a !== undefined ? Maybe.just(a) : Maybe.nothing();
  }

  static of(a) {
    return Maybe.just(a)
  }

  get isNothing() {
    return false;
  }

  get isJust() {
    return false;
  }
}

class Just extends Maybe {
  constructor(value) {
    super();
    this._value = value;
  }

  get value() {
    return this._value;
  }

  map(f) {
    return Maybe.of(f(this.value));
  }

  getOrElse() {
    return this.value;
  }

  filter(f) {
    return Maybe.fromNullLable(f(this.value) ? this.value : null)
  }

  isArray() {
    return this.filter((val) => val instanceof Array);
  }

  isObject() {
    return this.filter((val) => val instanceof Object);
  }

  get isJust() {
    return true;
  }

  toString() {
    return `Maybe.Just(${this.value})`
  }
}

class Nothing extends Maybe {
  map(f) {
    return this;
  }

  get value() {
    throw new TypeError("Can't extract the value of a Nothing.")
  }

  getOrElse(other) {
    return other;
  }

  filter() {
    return this;
  }

  isArray() {
    console.log(this)
    return this;
  }

  isObject() {
    return this;
  }

  get isNothing() {
    return true;
  }

  toString() {
    return 'Maybe.Nothing';
  }
}